package com.inwavetech.os.tests.sync.jsonparser;

import com.inwavetech.os.entity.Os;
import com.inwavetech.os.entity.enummap.EnumMap;
import com.inwavetech.os.sync.jsonparser.InvalidEntityJsonException;
import com.inwavetech.os.sync.jsonparser.BaseJsonParser;
import com.inwavetech.os.tests.sync.util.DateHandler;
import com.inwavetech.os.util.SyncDateFormat;

import junit.framework.TestCase;

import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.util.Date;
import java.util.concurrent.Callable;

/**
 * Created by jgskin on 3/5/14.
 */
abstract public class BaseJsonParserTest extends TestCase {

    protected BaseJsonParser jsonParser;
    protected JSONObject aJson;
    protected Object anObject;
    private DateHandler dateHandler;

    public void testInvalidJson_invalidId() throws InvalidEntityJsonException, JSONException {
        // invalid values
        aJson.put("id", "");
        assertInvalidEntityJsonException("id");

        aJson.put("id", " ");
        assertInvalidEntityJsonException("id");

        aJson.put("id", "  ");
        assertInvalidEntityJsonException("id");
    }

    protected void assertInvalidEntityJsonException(String expectedInvalidKey) throws JSONException {
        try {
            parse();
            fail(String.format("no invalid entity json exception thrown for '%s'", expectedInvalidKey));
        } catch (InvalidEntityJsonException e) {
            assertTrue(e.getInvalidKeys().contains(expectedInvalidKey));
        }
    }

    protected void removeKeyAndTestException(String keyToRemove) throws JSONException {
        aJson.remove(keyToRemove);
        assertInvalidEntityJsonException(keyToRemove);
    }

    protected void parse() throws InvalidEntityJsonException, JSONException {
        jsonParser.parse(aJson, anObject);
    }

    protected DateHandler getDateHandler() throws ParseException {
        if (dateHandler == null) {
            dateHandler = new DateHandler();
        }

        return dateHandler;
    }

    protected void assignAndParse(String keyname, Object value) throws JSONException, InvalidEntityJsonException {
        aJson.put(keyname, value);
        parse();
    }

    protected void assertEnumEntry(
            String keyName,
            boolean required,
            EnumMap map,
            Enum enumValue,
            Callable<Enum> getObjectValue) throws Exception {

        // valid values
        assignAndParse(keyName, map.getId(enumValue));
        assertEquals(enumValue, getObjectValue.call());

        assertBlankValue(keyName, required, getObjectValue);

        // invalid values
        aJson.put(keyName, "nonvalid");
        assertInvalidEntityJsonException(keyName);

        aJson.put(keyName, "12.40");
        assertInvalidEntityJsonException(keyName);

        aJson.put(keyName, "1213454");
        assertInvalidEntityJsonException(keyName);
    }

    protected void assertBlankValue(String keyName, boolean required, Callable getObjectValue) throws Exception {
        if (required) {
            assertInvalidBlankValue(keyName);
        } else {
            assertValidBlankValue(keyName, getObjectValue);
        }
    }

    protected void assertValidBlankValue(String keyName, Callable getObjectValue) throws Exception {
        // a blank string should be valid
        assignAndParse(keyName, "");
        // verify the parsed value
        assertNull(getObjectValue.call());
    }

    protected void assertInvalidBlankValue(String keyName) throws JSONException {
        aJson.put(keyName, "");
        assertInvalidEntityJsonException(keyName);
    }
}
